{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%env MODEL=/opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/intel/person-vehicle-bike-detection-crossroad-0078/FP32/person-vehicle-bike-detection-crossroad-0078.xml\n",
    "%env LABEL_FILE=../resources/labels.txt\n",
    "%env DEVICE=CPU\n",
    "%env LOOP_VIDEO=False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#!/usr/bin/env python3\n",
    "\"\"\"\n",
    "* Copyright (c) 2018 Intel Corporation.\n",
    "*\n",
    "* Permission is hereby granted, free of charge, to any person obtaining\n",
    "* a copy of this software and associated documentation files (the\n",
    "* \"Software\"), to deal in the Software without restriction, including\n",
    "* without limitation the rights to use, copy, modify, merge, publish,\n",
    "* distribute, sublicense, and/or sell copies of the Software, and to\n",
    "* permit persons to whom the Software is furnished to do so, subject to\n",
    "* the following conditions:\n",
    "*\n",
    "* The above copyright notice and this permission notice shall be\n",
    "* included in all copies or substantial portions of the Software.\n",
    "*\n",
    "* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n",
    "* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n",
    "* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n",
    "* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n",
    "* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n",
    "* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n",
    "* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
    "\"\"\"\n",
    "\n",
    "\n",
    "from __future__ import print_function\n",
    "import sys\n",
    "import os\n",
    "from argparse import ArgumentParser\n",
    "import cv2\n",
    "import numpy\n",
    "import time\n",
    "import collections\n",
    "import queue\n",
    "import signal\n",
    "import json\n",
    "import pathlib\n",
    "from inference import Network\n",
    "\n",
    "# CONSTANTS\n",
    "CONFIG_FILE = '../resources/config.json'\n",
    "EVENT_FILE = \"../UI/resources/video_data/events.json\"\n",
    "DATA_FILE = \"../UI/resources/video_data/data.json\"\n",
    "TARGET_DEVICE = \"CPU\"\n",
    "OUTPUT_VIDEO_PATH = \"../UI/resources/videos\"\n",
    "CPU_EXTENSION = \"\"\n",
    "LOOP_VIDEO = False\n",
    "UI = False\n",
    "CONF_THRESHOLD_VALUE = 0.55\n",
    "LOG_FILE_PATH = \"./intruders.log\"\n",
    "LOG_WIN_HEIGHT = 432\n",
    "LOG_WIN_WIDTH = 410\n",
    "CONF_CANDIDATE_CONFIDENCE = 4\n",
    "CODEC = 0x31637661\n",
    "\n",
    "# Opencv windows per each row\n",
    "CONF_WINDOW_COLUMNS = 2\n",
    "\n",
    "# Global variables\n",
    "model_xml = ''\n",
    "model_bin = ''\n",
    "conf_labels_file_path = ''\n",
    "video_caps = []\n",
    "accepted_devices = [\"CPU\", \"GPU\", \"HETERO:FPGA,CPU\", \"MYRIAD\", \"HDDL\"]\n",
    "is_async_mode = True\n",
    "\n",
    "# Event class to store the intruder details\n",
    "class Event:\n",
    "    def __init__(self, event_time=None, intruder=None, count=None, frame=None):\n",
    "        self.time = event_time\n",
    "        self.intruder = intruder\n",
    "        self.count = count\n",
    "        self.frame = frame\n",
    "\n",
    "\n",
    "# VideoCap class to manage the input source\n",
    "class VideoCap:\n",
    "    def __init__(self, vc, cam_name, cams, is_cam):\n",
    "        self.input_width = vc.get(3)\n",
    "        self.input_height = vc.get(4)\n",
    "        self.vc = vc\n",
    "        self.cam_name = cam_name\n",
    "        self.is_cam = is_cam\n",
    "        self.no_of_labels = 0\n",
    "        self.last_correct_count = []\n",
    "        self.total_count = []\n",
    "        self.current_count = []\n",
    "        self.changed_count = []\n",
    "        self.candidate_count = []\n",
    "        self.candidate_confidence = []\n",
    "        self.frame = None\n",
    "        self.loop_frames = 0\n",
    "        self.frame_count = 0\n",
    "        self.events = []\n",
    "        self.video_name = 'video{}.mp4'.format(cams)\n",
    "        self.vw = None\n",
    "\n",
    "    def init(self, size):\n",
    "        self.no_of_labels = size\n",
    "        for i in range(size):\n",
    "            self.last_correct_count.append(0)\n",
    "            self.total_count.append(0)\n",
    "            self.changed_count.append(False)\n",
    "            self.current_count.append(0)\n",
    "            self.candidate_count.append(0)\n",
    "            self.candidate_confidence.append(0)\n",
    "\n",
    "    def init_vw(self, h, w):\n",
    "        self.vw = cv2.VideoWriter(os.path.join(OUTPUT_VIDEO_PATH, self.video_name), CODEC,\n",
    "                                  self.vc.get(cv2.CAP_PROP_FPS), (w, h), True)\n",
    "        if not self.vw.isOpened():\n",
    "            return -1, self.video_name\n",
    "        return 0, ''\n",
    "\n",
    "\n",
    "def parse_args():\n",
    "    \"\"\"\n",
    "    Parse the command line argument\n",
    "\n",
    "    :return status: 0 on success, negative value on failure\n",
    "    \"\"\"\n",
    "    global LOOP_VIDEO\n",
    "    global conf_labels_file_path\n",
    "    global model_xml\n",
    "    global model_bin\n",
    "    global CPU_EXTENSION\n",
    "    global UI\n",
    "    global TARGET_DEVICE\n",
    "    global is_async_mode\n",
    "\n",
    "    try:\n",
    "        model_xml = os.environ[\"MODEL\"]\n",
    "        model_bin = os.path.splitext(model_xml)[0] + \".bin\"\n",
    "    except:\n",
    "        return -2\n",
    "\n",
    "    try:\n",
    "        conf_labels_file_path = os.environ[\"LABEL_FILE\"]\n",
    "    except:\n",
    "        return -3\n",
    "\n",
    "    CPU_EXTENSION = os.environ[\n",
    "        'CPU_EXTENSION'] if 'CPU_EXTENSION' in os.environ.keys() else None\n",
    "\n",
    "    try:\n",
    "        LOOP_VIDEO = os.environ[\"LOOP_VIDEO\"]\n",
    "        if LOOP_VIDEO == \"True\" or LOOP_VIDEO == \"true\":\n",
    "            LOOP_VIDEO = True\n",
    "        elif LOOP_VIDEO == \"False\" or LOOP_VIDEO == \"false\":\n",
    "            LOOP_VIDEO = False\n",
    "        else:\n",
    "            print(\"Invalid input for LOOP_VIDEO. Defaulting to LOOP_VIDEO = False\")\n",
    "            LOOP_VIDEO = False\n",
    "    except:\n",
    "        LOOP_VIDEO = False\n",
    "\n",
    "    if 'DEVICE' in os.environ.keys():\n",
    "        TARGET_DEVICE = os.environ['DEVICE']\n",
    "\n",
    "    try:\n",
    "        UI = os.environ[\"UI\"]\n",
    "        if UI == \"True\" or UI == \"true\":\n",
    "            UI = True\n",
    "        elif UI == \"False\" or UI == \"false\":\n",
    "            UI = False\n",
    "        else:\n",
    "            print(\"Invalid input for UI. Defaulting to UI = False\")\n",
    "            UI = False\n",
    "    except:\n",
    "        UI = False\n",
    "\n",
    "    if 'FLAG' in os.environ.keys():\n",
    "        async_mode = os.environ['FLAG']\n",
    "        if async_mode == \"sync\":\n",
    "            is_async_mode = False\n",
    "        else:\n",
    "            is_async_mode = True\n",
    "\n",
    "def check_args():\n",
    "    \"\"\"\n",
    "    Validate the command line arguments\n",
    "    :return status: 0 on success, negative value on failure\n",
    "    \"\"\"\n",
    "    global model_xml\n",
    "    global conf_labels_file_path\n",
    "\n",
    "    if model_xml == '':\n",
    "        return -2\n",
    "\n",
    "    if conf_labels_file_path == '':\n",
    "        return -3\n",
    "\n",
    "    if 'MULTI' not in TARGET_DEVICE and TARGET_DEVICE not in accepted_devices:\n",
    "        print(\"Unsupported device: \" + TARGET_DEVICE)\n",
    "        return -17\n",
    "    elif 'MULTI' in TARGET_DEVICE:\n",
    "        target_devices = TARGET_DEVICE.split(':')[1].split(',')\n",
    "        for multi_device in target_devices:\n",
    "            if multi_device not in accepted_devices:\n",
    "                print(\"Unsupported device: \" + TARGET_DEVICE)\n",
    "                return -17\n",
    "    return 0\n",
    "\n",
    "\n",
    "def get_used_labels(req_labels):\n",
    "    \"\"\"\n",
    "    Read the model's label file and get the position of labels required by the application\n",
    "\n",
    "    :param req_labels: intruders to be detected in the input source\n",
    "    :return status: 0 on success, negative value on failure\n",
    "            labels: On success, list of labels present in model's label file\n",
    "            used_labels: On success, list of bool values where true indicates that a label in labels list at that position is\n",
    "                        used in the application\n",
    "    \"\"\"\n",
    "    global conf_labels_file_path\n",
    "    used_labels = []\n",
    "\n",
    "    if conf_labels_file_path:\n",
    "        labels = []\n",
    "        with open(conf_labels_file_path, 'r') as label_file:\n",
    "            if not label_file:\n",
    "                return [-4, [], []]\n",
    "            labels = [x.strip() for x in label_file]\n",
    "\n",
    "        if not labels:\n",
    "            return [-5, [], []]\n",
    "\n",
    "        for label in labels:\n",
    "            if label in req_labels:\n",
    "                used_labels.append(True)\n",
    "            else:\n",
    "                used_labels.append(False)\n",
    "\n",
    "        return [0, labels, used_labels]\n",
    "\n",
    "    return [-6, [], []]\n",
    "\n",
    "\n",
    "def get_input():\n",
    "    \"\"\"\n",
    "    Parse the configuration file\n",
    "\n",
    "    :return status: 0 on success, negative value on failure\n",
    "            streams: On success, list of VideoCap containing configuration file data\n",
    "            labels: On success, labels or intruder to be detected\n",
    "    \"\"\"\n",
    "    global CONFIG_FILE\n",
    "    global video_caps\n",
    "    labels = []\n",
    "    streams = []\n",
    "\n",
    "    assert os.path.isfile(CONFIG_FILE), \"{} file doesn't exist\".format(CONFIG_FILE)\n",
    "    config = json.loads(open(CONFIG_FILE).read())\n",
    "    for id, item in enumerate(config['inputs']):\n",
    "        for idx, video in enumerate(item['video']):\n",
    "            cams = idx + 1\n",
    "            cam_name = \"Cam {}\".format(idx)\n",
    "            if video.isdigit():\n",
    "                video_cap = VideoCap(cv2.VideoCapture(int(video)), cam_name, cams, is_cam=True)\n",
    "            else:\n",
    "                if os.path.isfile(video):\n",
    "                    video_cap = VideoCap(cv2.VideoCapture(video), cam_name, cams, is_cam=False)\n",
    "                else:\n",
    "                    return [-8, [video]]\n",
    "            video_caps.append(video_cap)\n",
    "        labels = item['label']\n",
    "\n",
    "    for video_cap in video_caps:\n",
    "        if not video_cap.vc.isOpened():\n",
    "            return [-9, [video_cap.cam_name]]\n",
    "\n",
    "        video_cap.init(len(labels))\n",
    "    return [0, labels]\n",
    "\n",
    "\n",
    "def save_json():\n",
    "    \"\"\"\n",
    "    Write the video results to json files\n",
    "\n",
    "    :return status: 0 on success, negative value on failure\n",
    "    \"\"\"\n",
    "    global video_caps\n",
    "    global EVENT_FILE\n",
    "    global DATA_FILE\n",
    "    events = []\n",
    "    if video_caps:\n",
    "        events = video_caps[0].events\n",
    "    total = 0\n",
    "    event_json = open(EVENT_FILE, 'w')\n",
    "    if not event_json:\n",
    "        return -10\n",
    "\n",
    "    data_json = open(DATA_FILE, 'w')\n",
    "    if not data_json:\n",
    "        return -11\n",
    "\n",
    "    data_json.write(\"{\\n\\t\\\"video1\\\": {\\n\")\n",
    "    event_json.write(\"{\\n\\t\\\"video1\\\": {\\n\")\n",
    "    events_size = len(events) - 1\n",
    "    if events:\n",
    "        fps = video_caps[0].vc.get(cv2.CAP_PROP_FPS)\n",
    "        for i in range(events_size):\n",
    "            event_json.write(\"\\t\\t\\\"%d\\\":{\\n\" % (i))\n",
    "            event_json.write(\"\\t\\t\\t\\\"time\\\":\\\"%s\\\",\\n\" % events[i].time)\n",
    "            event_json.write(\"\\t\\t\\t\\\"content\\\":\\\"%s\\\",\\n\" % events[i].intruder)\n",
    "            event_json.write(\"\\t\\t\\t\\\"videoTime\\\":\\\"%d\\\"\\n\" % float(events[i].frame / fps))\n",
    "            event_json.write(\"\\t\\t},\\n\")\n",
    "            data_json.write(\"\\t\\t\\\"%d\\\": \\\"%d\\\",\\n\" % (float(events[i].frame / fps), events[i].count))\n",
    "        event_json.write(\"\\t\\t\\\"%d\\\":{\\n\" % events_size)\n",
    "        event_json.write(\"\\t\\t\\t\\\"time\\\":\\\"%s\\\",\\n\" % events[events_size].time)\n",
    "        event_json.write(\"\\t\\t\\t\\\"content\\\":\\\"%s\\\",\\n\" % events[events_size].intruder)\n",
    "        event_json.write(\"\\t\\t\\t\\\"videoTime\\\":\\\"%d\\\"\\n\" % float(events[events_size].frame / fps))\n",
    "        event_json.write(\"\\t\\t}\\n\")\n",
    "        data_json.write(\"\\t\\t\\\"%d\\\": \\\"%d\\\"\\n\" % (float(events[events_size].frame / fps), events[events_size].count))\n",
    "        total = events[events_size].count\n",
    "    event_json.write(\"\\t}\\n\")\n",
    "    event_json.write(\"}\")\n",
    "    data_json.write(\"\\t},\\n\")\n",
    "    data_json.write(\"\\t\\\"totals\\\":{\\n\")\n",
    "    data_json.write(\"\\t\\t\\\"video1\\\": \\\"%d\\\"\\n\" % total)\n",
    "    data_json.write(\"\\t}\\n\")\n",
    "    data_json.write(\"}\")\n",
    "    event_json.close()\n",
    "    data_json.close()\n",
    "    return 0\n",
    "\n",
    "\n",
    "def arrange_windows():\n",
    "    \"\"\"\n",
    "    Arranges the windows so that they are not overlapping\n",
    "\n",
    "    :return: None\n",
    "    \"\"\"\n",
    "    global CONF_WINDOW_COLUMNS\n",
    "    global video_caps\n",
    "    spacer = 470\n",
    "    row_spacer = 250\n",
    "    cols = 0\n",
    "    rows = 0\n",
    "    window_width = 768\n",
    "    window_height = 432\n",
    "\n",
    "    # Arrange log window\n",
    "    cv2.namedWindow(\"Intruder Log\", cv2.WINDOW_AUTOSIZE)\n",
    "    cv2.moveWindow(\"Intruder Log\", 0, 0)\n",
    "\n",
    "    # Arrange video windows\n",
    "    for idx in range(len(video_caps)):\n",
    "        if cols == CONF_WINDOW_COLUMNS:\n",
    "            rows += 1\n",
    "            cols = 1\n",
    "            cv2.namedWindow(video_caps[idx].cam_name, cv2.WINDOW_NORMAL)\n",
    "            cv2.resizeWindow(video_caps[idx].cam_name, window_width, window_height)\n",
    "            cv2.moveWindow(video_caps[idx].cam_name, spacer * cols, row_spacer * rows)\n",
    "        else:\n",
    "            cols += 1\n",
    "            cv2.namedWindow(video_caps[idx].cam_name, cv2.WINDOW_NORMAL)\n",
    "            cv2.resizeWindow(video_caps[idx].cam_name, window_width, window_height)\n",
    "            cv2.moveWindow(video_caps[idx].cam_name, spacer * cols, row_spacer * rows)\n",
    "\n",
    "\n",
    "# Signal handler\n",
    "def signal_handler(sig, frame):\n",
    "    global video_caps\n",
    "    global EVENT_FILE\n",
    "    global DATA_FILE\n",
    "    if video_caps:\n",
    "        ret = save_json()\n",
    "        if ret != 0:\n",
    "            if ret == -10:\n",
    "                print(\"Could not create event JSON file \" + EVENT_FILE + \"!\")\n",
    "            elif ret == -11:\n",
    "                print(\"Could not create data JSON file \" + DATA_FILE + \"!\")\n",
    "\n",
    "    clean_up()\n",
    "    sys.exit(0)\n",
    "\n",
    "\n",
    "def clean_up():\n",
    "    \"\"\"\n",
    "    Destroys all the opencv windows and releases the objects of videoCapture and videoWriter\n",
    "    \"\"\"\n",
    "    global video_caps\n",
    "    cv2.destroyAllWindows()\n",
    "    for video_cap in video_caps:\n",
    "        if video_cap.vw:\n",
    "            video_cap.vw.release()\n",
    "        if video_cap.vc:\n",
    "            video_cap.vc.release()\n",
    "\n",
    "\n",
    "def intruder_detector():\n",
    "    \"\"\"\n",
    "    Process the input source frame by frame and detects intruder, if any.\n",
    "\n",
    "    :return status: 0 on success, negative value on failure\n",
    "    \"\"\"\n",
    "    global CONF_CANDIDATE_CONFIDENCE\n",
    "    global LOG_WIN_HEIGHT\n",
    "    global LOG_WIN_WIDTH\n",
    "    global CONFIG_FILE\n",
    "    global video_caps\n",
    "    global conf_labels_file_path\n",
    "    global is_async_mode\n",
    "    global UI\n",
    "    global LOOP_VIDEO\n",
    "\n",
    "    parse_args()\n",
    "    ret = check_args()\n",
    "    if ret != 0:\n",
    "        return ret, \"\"\n",
    "\n",
    "    if not os.path.isfile(CONFIG_FILE):\n",
    "        return -12, \"\"\n",
    "\n",
    "    if not os.path.isfile(conf_labels_file_path):\n",
    "        return -13, \"\"\n",
    "\n",
    "    # Creates subdirectory to save output snapshots\n",
    "    pathlib.Path(os.getcwd() + '/output/').mkdir(parents=True, exist_ok=True)\n",
    "\n",
    "    # Read the configuration file\n",
    "    ret, req_labels = get_input()\n",
    "    if ret != 0:\n",
    "        return ret, req_labels[0]\n",
    "\n",
    "    if not video_caps:\n",
    "        return -14, ''\n",
    "\n",
    "    # Get the labels that are used in the application\n",
    "    ret, label_names, used_labels = get_used_labels(req_labels)\n",
    "    if ret != 0:\n",
    "        return ret, ''\n",
    "    if True not in used_labels:\n",
    "        return -15, ''\n",
    "\n",
    "    # Init a rolling log to store events\n",
    "    rolling_log_size = int((LOG_WIN_HEIGHT - 15) / 20)\n",
    "    log_list = collections.deque(maxlen=rolling_log_size)\n",
    "\n",
    "    # Open a file for intruder logs\n",
    "    log_file = open(LOG_FILE_PATH, 'w')\n",
    "    if not log_file:\n",
    "        return -16, ''\n",
    "\n",
    "    # Initializing VideoWriter for each source\n",
    "    if UI and not LOOP_VIDEO:\n",
    "        for video_cap in video_caps:\n",
    "            ret, ret_value = video_cap.init_vw(int(video_cap.input_height), int(video_cap.input_width))\n",
    "            if ret != 0:\n",
    "                return ret, ret_value\n",
    "\n",
    "    # Initialise the class\n",
    "    infer_network = Network()\n",
    "    # Load the network to IE plugin to get shape of input layer\n",
    "    n, c, h, w = infer_network.load_model(model_xml, TARGET_DEVICE, 1, 1, 2, CPU_EXTENSION)[1]\n",
    "    # Arrange windows so that they are not overlapping\n",
    "    arrange_windows()\n",
    "\n",
    "    min_fps = min([i.vc.get(cv2.CAP_PROP_FPS) for i in video_caps])\n",
    "    signal.signal(signal.SIGINT, signal_handler, )\n",
    "    no_more_data = [False] * len(video_caps)\n",
    "    start_time = time.time()\n",
    "    inf_time = 0\n",
    "    next_request_id = 1\n",
    "    cur_request_id = 0\n",
    "    # Main loop starts here. Loop over all the video captures\n",
    "\n",
    "    if is_async_mode:\n",
    "        print(\"Application running in async mode...\")\n",
    "    else:\n",
    "        print(\"Application running in sync mode...\")\n",
    "\n",
    "    while True:\n",
    "        for idx, video_cap in enumerate(video_caps):\n",
    "            # Get a new frame\n",
    "            vfps = int(round(video_cap.vc.get(cv2.CAP_PROP_FPS)))\n",
    "            for i in range(0, int(round(vfps / min_fps))):\n",
    "                if is_async_mode:\n",
    "                    ret, video_cap.next_frame = video_cap.vc.read()\n",
    "                else:\n",
    "                    ret, video_cap.frame = video_cap.vc.read()\n",
    "                video_cap.loop_frames += 1\n",
    "                # If no new frame or error in reading a frame, exit the loop\n",
    "                if not ret:\n",
    "                    no_more_data[idx] = True\n",
    "                    break\n",
    "            if no_more_data[idx]:\n",
    "                stream_end_frame = numpy.zeros((int(video_cap.input_height), int(video_cap.input_width), 1),\n",
    "                                               dtype='uint8')\n",
    "                stream_end_message = \"Stream from {} has ended.\".format(video_cap.cam_name)\n",
    "                cv2.putText(stream_end_frame, stream_end_message, (int(video_cap.input_width / 2) - 30,\n",
    "                                                                   int(video_cap.input_height / 2) - 30),\n",
    "                            cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)\n",
    "                cv2.imshow(video_cap.cam_name, stream_end_frame)\n",
    "                continue\n",
    "            for i in range(video_cap.no_of_labels):\n",
    "                video_cap.current_count[i] = 0\n",
    "                video_cap.changed_count[i] = False\n",
    "\n",
    "            # Resize to expected size (in model .xml file)\n",
    "            # Input frame is resized to infer resolution\n",
    "            if is_async_mode:\n",
    "                in_frame = cv2.resize(video_cap.next_frame, (w, h))\n",
    "                in_frame = in_frame.transpose((2, 0, 1))\n",
    "                in_frame = in_frame.reshape((n, c, h, w))\n",
    "\n",
    "                # Start asynchronous inference for specified request.\n",
    "                infer_network.exec_net(next_request_id, in_frame)\n",
    "                video_cap.frame = video_cap.next_frame\n",
    "                # Async enabled and only one video capture\n",
    "                if len(video_caps) == 1:\n",
    "                    videoCapResult = video_cap\n",
    "                # Async enabled and more than one video capture\n",
    "                else:\n",
    "                    # Get previous index\n",
    "                    videoCapResult = video_caps[idx - 1 if idx - 1 >= 0 else len(video_caps) - 1]\n",
    "\n",
    "            else:\n",
    "                in_frame = cv2.resize(video_cap.frame, (w, h))\n",
    "                in_frame = in_frame.transpose((2, 0, 1))\n",
    "                in_frame = in_frame.reshape((n, c, h, w))\n",
    "\n",
    "                # Start synchronous inference for specified request.\n",
    "                infer_network.exec_net(cur_request_id, in_frame)\n",
    "                videoCapResult = video_cap\n",
    "\n",
    "            inf_start = time.time()\n",
    "            # Wait for the result\n",
    "            if infer_network.wait(cur_request_id) == 0:\n",
    "                inf_time = time.time() - inf_start\n",
    "                # Results of the output layer of the network\n",
    "                res = infer_network.get_output(cur_request_id)\n",
    "                for obj in res[0][0]:\n",
    "                    label = int(obj[1]) - 1\n",
    "                    # Draw the bounding box around the object when the probability is more than specified threshold\n",
    "                    if obj[2] > CONF_THRESHOLD_VALUE and used_labels[label]:\n",
    "                        videoCapResult.current_count[label] += 1\n",
    "                        xmin = int(obj[3] * videoCapResult.input_width)\n",
    "                        ymin = int(obj[4] * videoCapResult.input_height)\n",
    "                        xmax = int(obj[5] * videoCapResult.input_width)\n",
    "                        ymax = int(obj[6] * videoCapResult.input_height)\n",
    "                        # Draw bounding box around the intruder detected\n",
    "                        cv2.rectangle(videoCapResult.frame, (xmin, ymin), (xmax, ymax), (0, 255, 0), 4, 16)\n",
    "\n",
    "                for i in range(videoCapResult.no_of_labels):\n",
    "                    if videoCapResult.candidate_count[i] == videoCapResult.current_count[i]:\n",
    "                        videoCapResult.candidate_confidence[i] += 1\n",
    "                    else:\n",
    "                        videoCapResult.candidate_confidence[i] = 0\n",
    "                        videoCapResult.candidate_count[i] = videoCapResult.current_count[i]\n",
    "\n",
    "                    if videoCapResult.candidate_confidence[i] == CONF_CANDIDATE_CONFIDENCE:\n",
    "                        videoCapResult.candidate_confidence[i] = 0\n",
    "                        videoCapResult.changed_count[i] = True\n",
    "                    else:\n",
    "                        continue\n",
    "\n",
    "                    if videoCapResult.current_count[i] > videoCapResult.last_correct_count[i]:\n",
    "                        videoCapResult.total_count[i] += videoCapResult.current_count[i] - videoCapResult.last_correct_count[i]\n",
    "                        det_objs = videoCapResult.current_count[i] - videoCapResult.last_correct_count[i]\n",
    "                        total_count = sum(videoCapResult.total_count)\n",
    "                        for det_obj in range(det_objs):\n",
    "                            current_time = time.strftime(\"%H:%M:%S\")\n",
    "                            log = \"{} - Intruder {} detected on {}\".format(current_time, label_names[i],\n",
    "                                                                           videoCapResult.cam_name)\n",
    "                            log_list.append(log)\n",
    "                            log_file.write(log + \"\\n\")\n",
    "                            event = Event(event_time=current_time, intruder=label_names[i], count=total_count,\n",
    "                                          frame=videoCapResult.frame_count)\n",
    "                            videoCapResult.events.append(event)\n",
    "\n",
    "                        snapshot_name = \"output/intruder_{}.png\".format(total_count)\n",
    "                        cv2.imwrite(snapshot_name, videoCapResult.frame)\n",
    "                    videoCapResult.last_correct_count[i] = videoCapResult.current_count[i]\n",
    "\n",
    "                # Create intruder log window, add logs to the frame and display it\n",
    "                log_window = numpy.zeros((LOG_WIN_HEIGHT, LOG_WIN_WIDTH, 1), dtype='uint8')\n",
    "                for i, log in enumerate(log_list):\n",
    "                    cv2.putText(log_window, log, (10, 20 * i + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)\n",
    "                cv2.imshow(\"Intruder Log\", log_window)\n",
    "                videoCapResult.frame_count += 1\n",
    "\n",
    "                # Video output\n",
    "                if UI and not LOOP_VIDEO:\n",
    "                    videoCapResult.vw.write(videoCapResult.frame)\n",
    "\n",
    "                log_message = \"Async mode is on.\" if is_async_mode else \\\n",
    "                    \"Async mode is off.\"\n",
    "                cv2.putText(videoCapResult.frame, log_message, (10, int(videoCapResult.input_height) - 50),\n",
    "                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 10, 10), 1)\n",
    "                inf_time_message = \"Inference time: N\\A for async mode\" if is_async_mode else \\\n",
    "                    \"Inference time: {:.3f} ms\".format(inf_time * 1000)\n",
    "                cv2.putText(videoCapResult.frame, inf_time_message, (10, int(videoCapResult.input_height) - 30),\n",
    "                            cv2.FONT_HERSHEY_COMPLEX, 0.5, (200, 10, 10), 1)\n",
    "                fps_time = time.time() - start_time\n",
    "                fps_message = \"FPS: {:.3f} fps\".format(1/fps_time)\n",
    "                cv2.putText(videoCapResult.frame, fps_message, (10, int(videoCapResult.input_height) - 10),\n",
    "                            cv2.FONT_HERSHEY_COMPLEX, 0.5, (200, 10, 10), 1)\n",
    "\n",
    "                # Display the video output\n",
    "                cv2.imshow(videoCapResult.cam_name, videoCapResult.frame)\n",
    "\n",
    "            start_time = time.time()\n",
    "\n",
    "            # Loop video to mimic continuous input if LOOP_VIDEO flag is True\n",
    "            if LOOP_VIDEO and not videoCapResult.is_cam:\n",
    "                vfps = int(round(videoCapResult.vc.get(cv2.CAP_PROP_FPS)))\n",
    "                # If a video capture has ended restart it\n",
    "                if videoCapResult.loop_frames > videoCapResult.vc.get(cv2.CAP_PROP_FRAME_COUNT) - int(round(vfps / min_fps)):\n",
    "                    videoCapResult.loop_frames = 0\n",
    "                    videoCapResult.vc.set(cv2.CAP_PROP_POS_FRAMES, 0)\n",
    "\n",
    "            if is_async_mode:\n",
    "                # Swap infer request IDs\n",
    "                cur_request_id, next_request_id = next_request_id, cur_request_id\n",
    "\n",
    "        if cv2.waitKey(1) == 27:\n",
    "            break\n",
    "\n",
    "        if cv2.waitKey(1) == 9:\n",
    "            is_async_mode = not is_async_mode\n",
    "            print(\"Switched to {} mode\".format(\"async\" if is_async_mode else \"sync\"))\n",
    "\n",
    "        if False not in no_more_data:\n",
    "            break\n",
    "\n",
    "    ret = save_json()\n",
    "    if ret != 0:\n",
    "        return ret, ''\n",
    "\n",
    "    infer_network.clean()\n",
    "    log_file.close()\n",
    "    return [0, '']\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    status, value = intruder_detector()\n",
    "\n",
    "    if status == 0:\n",
    "        print(\"Success!\")\n",
    "    elif status == -1:\n",
    "        print(\"Could not open for write\" + value + \"!\")\n",
    "    elif status == -2:\n",
    "        print(\"Path to the .xml file not specified!\")\n",
    "        print(\"Specify it using %env MODEL\")\n",
    "    elif status == -3:\n",
    "        print(\"You need to specify the path to the labels file\")\n",
    "        print(\"Specify it using %env LABEL_FILE\")\n",
    "    elif status == -4:\n",
    "        print(\"Error in opening labels file!\")\n",
    "    elif status == -5:\n",
    "        print(\"No labels found in label file!\")\n",
    "    elif status == -6:\n",
    "        print(\"Labels file not found!\")\n",
    "    elif status == -7:\n",
    "        print(\"Error in opening Configuration file \" + CONFIG_FILE + \"!\")\n",
    "    elif status == -8:\n",
    "        print(\"Could not find the video file \" + value + \"!\")\n",
    "    elif status == -9:\n",
    "        print(\"\\nCould not open \" + value + \" for reading!\")\n",
    "    elif status == -10:\n",
    "        print(\"Could not create event JSON file \" + EVENT_FILE + \"!\")\n",
    "    elif status == -11:\n",
    "        print(\"Could not create data JSON file \" + DATA_FILE + \"!\")\n",
    "    elif status == -12:\n",
    "        print(CONFIG_FILE + \" configuration file not found!\")\n",
    "    elif status == -13:\n",
    "        print(conf_labels_file_path + \" label file not found!\")\n",
    "    elif status == -14:\n",
    "        print(\"No input source found in configuration file!\")\n",
    "    elif status == -15:\n",
    "        print(\"Error: No labels currently in use. Please edit \" + CONFIG_FILE+\" file!\")\n",
    "    elif status == -16:\n",
    "        print(\"Error in opening intruder log file!\")\n",
    "    elif status == -17:\n",
    "        print(\"Path to cpu extensions library path not specified\")\n",
    "        print(\"Specify it using %env CPU_EXTENSION\")\n",
    "    else:\n",
    "        print(\"Unknown error occurred!\")\n",
    "\n",
    "    clean_up()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
